package org.jeecg.modules.nikeProject.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.modules.nikeProject.entity.SportsProject;
import org.jeecg.modules.nikeProject.entity.SportsProjectCaseSummary;
import org.jeecg.modules.nikeProject.entity.SportsProjectStatData;
import org.jeecg.modules.nikeProject.entity.SportsRepetitionLog;
import org.jeecg.modules.nikeProject.entity.vo.CompareVO;
import org.jeecg.modules.nikeProject.mapper.SportsProjectCaseSummaryMapper;
import org.jeecg.modules.nikeProject.mapper.SportsProjectMapper;
import org.jeecg.modules.nikeProject.mapper.SportsRepetitionLogMapper;
import org.jeecg.modules.nikeProject.service.ISportsProjectCaseSummaryService;
import org.jeecg.modules.util.JaccardSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Description: 案例内容总结表
 * @Author: jeecg-boot
 * @Date:   2025-07-08
 * @Version: V1.0
 */
@Service
@Slf4j
public class SportsProjectCaseSummaryServiceImpl extends ServiceImpl<SportsProjectCaseSummaryMapper, SportsProjectCaseSummary> implements ISportsProjectCaseSummaryService {

    @Autowired
    private SportsProjectCaseSummaryMapper sportsProjectCaseSummaryMapper;
    @Autowired
    private SportsRepetitionLogMapper sportsRepetitionLogMapper;
    @Autowired
    private SportsProjectMapper sportsProjectMapper;
    private final static String filePath = "repetition_data.xlsx";
    /**
     * 案例比较
     * @return
     */
    @Override
    public Result<?> caseCompare(Integer year, String projectId) {
        Calendar calendar = Calendar.getInstance();
        Integer currentYear = calendar.get(Calendar.YEAR);
        //1、获取当前年案例列表
        List<SportsProjectCaseSummary> currentList =  getCaseSummaryList(currentYear, projectId);
        //2.获取2023年案例列表
        List<SportsProjectCaseSummary> hisList = getCaseSummaryList(year, null);
        for (SportsProjectCaseSummary currentCaseSummary : currentList) {
            log.info("===============多线程去重开始=================");
            long current = System.currentTimeMillis();
            compareCase(currentCaseSummary, hisList);
            log.info("案例：{}去重处理理完成，耗时：{}毫秒", currentCaseSummary.getProjectId(), System.currentTimeMillis() - current);
        }
        return Result.OK("success");
    }

    /**
     * 更新案例去重比例
     * @return
     */
    @Override
    public Result<?> updateRepetitionRate() {
        Calendar calendar = Calendar.getInstance();
        Integer currentYear = calendar.get(Calendar.YEAR);
        List<SportsProject> list = getSportsProjectList(currentYear);
        for (SportsProject sportsProject : list) {
            SportsRepetitionLog sportsRepetitionLog = getRepetitionLog(sportsProject.getId());
            if (sportsRepetitionLog != null) {
                log.info("更新的案例为：{} ", sportsProject.getId());
                int cnt = getCnt(sportsRepetitionLog);
                if (cnt > 0) {
                    BigDecimal rate = sportsRepetitionLog.getTotalRate().divide(new BigDecimal(cnt), new MathContext(2, RoundingMode.HALF_UP));
                    sportsProject.setRepetitionRate(rate);
                } else {
                    sportsProject.setRepetitionRate(sportsRepetitionLog.getTotalRate());
                }
                sportsProject.setHisProjectId(sportsRepetitionLog.getHisProjectId());
                sportsProject.setFirstAuditStatus(CommonConstant.PROJECT_FIRST_AUDIT_STATUS_FINISH);
                sportsProjectMapper.updateById(sportsProject);
            }
        }
        return Result.OK("success");
    }

    @Override
    public Result<?> top200Compare(Integer year) {
        this.caseCompare(year, null);
        List<SportsProject> list = getTop200Project(year);
        List<CompareVO> compareVOList = new ArrayList<>();
        list.forEach(x -> {
            SportsRepetitionLog repetitionLog = getRepetitionLog(x.getId());
            if (repetitionLog != null) {
                CompareVO compareVO = new CompareVO();
                compareVO.setProjectId(repetitionLog.getProjectId());
                compareVO.setHisProjectId(repetitionLog.getHisProjectId());
                int cnt = getCnt(repetitionLog);
                if (cnt > 0) {
                    BigDecimal rate = repetitionLog.getTotalRate().divide(new BigDecimal(cnt), new MathContext(2, RoundingMode.HALF_UP));
                    compareVO.setRepetitionRate(rate);
                } else {
                    compareVO.setRepetitionRate(repetitionLog.getTotalRate());
                }
                compareVOList.add(compareVO);
            }
        });

        if (null != compareVOList && compareVOList.size() > 0) {
            writeListToExcel(compareVOList);
        }
        return Result.OK("success");
    }

    // 将List数据写入Excel文件
    public static void writeListToExcel(List<CompareVO> list) {
        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        // 创建一个工作表
        Sheet sheet = workbook.createSheet("Case Repetition Data");

        // 创建表头
        Row headerRow = sheet.createRow(0);
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headerStyle.setBorderTop(BorderStyle.THIN);
        headerStyle.setBorderBottom(BorderStyle.THIN);
        headerStyle.setBorderLeft(BorderStyle.THIN);
        headerStyle.setBorderRight(BorderStyle.THIN);

        String[] headers = {"案例编号", "历史案例编号", "重复率"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }

        // 填充数据
        for (int i = 0; i < list.size(); i++) {
            Row row = sheet.createRow(i + 1);
            CompareVO statData = list.get(i);

            // 设置单元格样式
            CellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setBorderTop(BorderStyle.THIN);
            cellStyle.setBorderBottom(BorderStyle.THIN);
            cellStyle.setBorderLeft(BorderStyle.THIN);
            cellStyle.setBorderRight(BorderStyle.THIN);

            // 写入数据
            Cell dateCell = row.createCell(0);
            dateCell.setCellValue(statData.getProjectId());
            dateCell.setCellStyle(cellStyle);

            Cell pvCell = row.createCell(1);
            pvCell.setCellValue(statData.getHisProjectId());
            pvCell.setCellStyle(cellStyle);

            Cell uvCell = row.createCell(2);
            uvCell.setCellValue(statData.getRepetitionRate().doubleValue());
            uvCell.setCellStyle(cellStyle);
        }

        // 自动调整列宽
        for (int i = 0; i < headers.length; i++) {
            sheet.autoSizeColumn(i);
        }

        // 保存到文件
        try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
            workbook.write(fileOut);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public List<SportsProject> getTop200Project(Integer year){
        Calendar calendar = Calendar.getInstance();
        LambdaQueryWrapper<SportsProject> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SportsProject::getIzActive, CommonConstant.COMMON_STATUS_N)
                .eq(SportsProject::getIzTop200, CommonConstant.COMMON_STATUS_Y)
                .eq(SportsProject::getYear, calendar.get(Calendar.YEAR));
        return sportsProjectMapper.selectList(queryWrapper);
    }

    private static int getCnt(SportsRepetitionLog sportsRepetitionLog) {
        int cnt = 0;
        if (sportsRepetitionLog.getChapter1Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        if (sportsRepetitionLog.getChapter2Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        if (sportsRepetitionLog.getChapter3Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        if (sportsRepetitionLog.getChapter4Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        if (sportsRepetitionLog.getChapter5Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        if (sportsRepetitionLog.getChapter6Rate().compareTo(BigDecimal.ZERO) > 0) {
            cnt = cnt + 1;
        }
        return cnt;
    }

    public void compareCase(SportsProjectCaseSummary caseSummary, List<SportsProjectCaseSummary> hisList) {
        try {
            ExecutorService executor = Executors.newFixedThreadPool(20); // 创建一个固定大小的线程池
            executor.submit(() -> {
                // 提交给线程池的任务
                compare(caseSummary, hisList);
            });
            executor.shutdown(); // 关闭线程池
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void compare(SportsProjectCaseSummary caseSummary, List<SportsProjectCaseSummary> hisCaseList){
        for (SportsProjectCaseSummary hisCase : hisCaseList) {
            if (!caseSummary.getProjectId().equals(hisCase.getProjectId())) {
                SportsRepetitionLog sportsRepetitionLog = getSportsRepetitionLog(caseSummary.getProjectId(), hisCase.getProjectId());
                if (null == sportsRepetitionLog) {
                    log.info("开始记录去重日志");
                    sportsRepetitionLog = new SportsRepetitionLog();
                    sportsRepetitionLog.setProjectId(caseSummary.getProjectId());
                    sportsRepetitionLog.setHisProjectId(hisCase.getProjectId());
                    sportsRepetitionLog.setCaseType(caseSummary.getCaseType());
                    if (izSameSportEvents(caseSummary.getSportsEvent(), hisCase.getSportsEvent())) {
                        sportsRepetitionLog.setIzSameSportsEvent(CommonConstant.COMMON_STATUS_Y);
                    }
                    //chapter1
                    BigDecimal chapter1Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter1()) && !"".equals(hisCase.getChapter1())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter1(), hisCase.getChapter1());
                        chapter1Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter1Rate(chapter1Rate);

                    //chapter2
                    BigDecimal chapter2Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter2()) && !"".equals(hisCase.getChapter2())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter2(), hisCase.getChapter2());
                        chapter2Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter2Rate(chapter2Rate);

                    //chapter3
                    BigDecimal chapter3Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter3()) && !"".equals(hisCase.getChapter3())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter3(), hisCase.getChapter3());
                        chapter3Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter3Rate(chapter3Rate);

                    //chapter4
                    BigDecimal chapter4Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter4()) && !"".equals(hisCase.getChapter4())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter4(), hisCase.getChapter4());
                        chapter4Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter4Rate(chapter4Rate);

                    //chapter5
                    BigDecimal chapter5Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter5()) && !"".equals(hisCase.getChapter5())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter5(), hisCase.getChapter5());
                        chapter5Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter5Rate(chapter5Rate);

                    //chapter6
                    BigDecimal chapter6Rate = BigDecimal.ZERO;
                    if (!"".equals(caseSummary.getChapter6()) && !"".equals(hisCase.getChapter6())) {
                        double rate = JaccardSimilarity.jaccardSimilarity(caseSummary.getChapter6(), hisCase.getChapter6());
                        chapter6Rate = BigDecimal.valueOf(rate);
                    }
                    sportsRepetitionLog.setChapter6Rate(chapter6Rate);
                    sportsRepetitionLog.setTotalRate(getTotalRate(sportsRepetitionLog));
                    sportsRepetitionLogMapper.insert(sportsRepetitionLog);
                }
            }
        }
        log.info("当前案例：{}，去重比较完成！！！", caseSummary.getProjectId());
    }

    public boolean izSameSportEvents(String currentSportsEvent, String hisSportsEvent){
        if (!"".equals(currentSportsEvent) || currentSportsEvent != null){
            String [] arr = currentSportsEvent.split(",");
            for (int i = 0; i < arr.length; i++) {
                if (hisSportsEvent.contains(arr[i])){
                    return true;
                }
            }
        }
        return false;
    }

    public BigDecimal getTotalRate(SportsRepetitionLog repetitionLog){
        return repetitionLog.getChapter1Rate().add(repetitionLog.getChapter2Rate()).add(repetitionLog.getChapter3Rate()).add(repetitionLog.getChapter4Rate()).add(repetitionLog.getChapter5Rate()).add(repetitionLog.getChapter6Rate());
    }

    public List<SportsProjectCaseSummary> getCaseSummaryList(Integer year, String projectId){
        LambdaQueryWrapper<SportsProjectCaseSummary> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SportsProjectCaseSummary::getYear, year);
        if (null != projectId && !"".equals(projectId)){
            lambdaQueryWrapper.eq(SportsProjectCaseSummary::getProjectId, projectId);
        }
        lambdaQueryWrapper.eq(SportsProjectCaseSummary::getIzActive, CommonConstant.COMMON_STATUS_N);
        return sportsProjectCaseSummaryMapper.selectList(lambdaQueryWrapper);
    }

    public List<SportsProject> getSportsProjectList(Integer year){
        LambdaQueryWrapper<SportsProject> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SportsProject::getYear, year);
        lambdaQueryWrapper.eq(SportsProject::getIzActive, CommonConstant.COMMON_STATUS_N);
        lambdaQueryWrapper.eq(SportsProject::getRoleType, CommonConstant.ROLE_TYPE_TE);
        lambdaQueryWrapper.gt(SportsProject::getProjectStatus, CommonConstant.PROJECT_STATUS_PENDING);
        lambdaQueryWrapper.isNull(SportsProject::getRepetitionRate);
        lambdaQueryWrapper.eq(SportsProject::getFirstAuditStatus, CommonConstant.PROJECT_FIRST_AUDIT_STATUS_PENDING);
        return sportsProjectMapper.selectList(lambdaQueryWrapper);
    }

    public SportsRepetitionLog getRepetitionLog(String projectId){
        LambdaQueryWrapper<SportsRepetitionLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SportsRepetitionLog::getProjectId, projectId);
        lambdaQueryWrapper.orderByDesc(SportsRepetitionLog::getTotalRate);
        List<SportsRepetitionLog> list = sportsRepetitionLogMapper.selectList(lambdaQueryWrapper);
        if (null != list && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    public SportsRepetitionLog getSportsRepetitionLog(String projectId, String hisProjectId){
        LambdaQueryWrapper<SportsRepetitionLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SportsRepetitionLog::getProjectId, projectId);
        lambdaQueryWrapper.eq(SportsRepetitionLog::getHisProjectId, hisProjectId);
        return sportsRepetitionLogMapper.selectOne(lambdaQueryWrapper);
    }
}
